﻿//using MslDiary.HTMLConverter;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;

namespace HtmlEditor
{
    public class RichTextBoxHelper
    {
        /// <summary>
        /// 设置Boder背景图片
        /// </summary>
        /// <param name="boder"></param>
        /// <param name="imgPath"></param>
        public static void SetBackground(System.Windows.Controls.Control boder, string imgPath)
        {
            if (String.IsNullOrEmpty(imgPath) || !File.Exists(imgPath))
                return;

            try
            {
                ImageBrush brush = new ImageBrush();
                brush.ImageSource = new BitmapImage(new Uri(imgPath));
                brush.Stretch = Stretch.Fill;
                boder.Background = brush;
            }
            catch (Exception)
            {

            }
        }

        //图片占位符格式：[$IMG-0-16-16$]=>0-16-16 分别代表图片链接地址、宽度、高度 正则为：\[\$IMG\-\d+\-\d+\-\d+\$\]
        /// <summary>
        /// 获取 RickTextBox 中的内容 且转换为 HTML 格式 
        /// </summary>
        /// <returns></returns>
        public static string GetHtml(RichTextBox rtbId)
        {
            string result = String.Empty;
            result = System.Windows.Markup.XamlWriter.Save(rtbId.Document);
            result = HtmlFromXamlConverter.ConvertXamlToHtml(result);
            return result;
        }
        /// <summary>
        /// 获取 RickTextBox 中的内容 且转换为 HTML 格式 
        /// </summary>
        /// <returns></returns>
        public static string GetXmal(RichTextBox rtbId)
        {
            string xaml = System.Windows.Markup.XamlWriter.Save(rtbId.Document);
            return xaml;
        }
        /// <summary>
        /// 获取 RickTextBox 纯文本内容
        /// </summary>
        /// <returns></returns>
        public static string GetText(RichTextBox rtbId)
        {
            TextRange range = new TextRange(rtbId.Document.ContentStart, rtbId.Document.ContentEnd);
            return range.Text;
        }
        /// <summary>
        /// 清除 RickTextBox 中的内容格式
        /// 目前只清除 SPAN标签
        /// </summary>
        /// <returns></returns>
        public static void FormatXaml(RichTextBox rtbId)
        {
            string xw = System.Windows.Markup.XamlWriter.Save(rtbId.Document);
            string xaml = GetXmal(rtbId);
            if (String.IsNullOrEmpty(xaml))
                return;
            xaml = Regex.Replace(xaml, "</?RUN(.*?)>", "", RegexOptions.IgnoreCase);
            LoadFromXaml(rtbId, xaml, true);
        }
        /// <summary>
        /// 设置内容
        /// </summary>
        /// <param name="html"></param>
        public static void LoadFromHtml(RichTextBox rtbId, string html)
        {
            if (String.IsNullOrEmpty(html))
            {
                rtbId.Document.Blocks.Clear();
                return;
            }
            if (!html.StartsWith("<HTML><TITLE>", StringComparison.CurrentCultureIgnoreCase))
                html = "<HTML><TITLE></TITLE><BODY>" + html + "</BODY></HTML>";

            string xaml = HtmlToXamlConverter.ConvertHtmlToXaml(html, true);
            xaml = Regex.Replace(xaml, @"file:///([\s\S]*?)res/face/", "file:///" + Global.FaceImagePath.Replace("\\", "/"), RegexOptions.IgnoreCase);//替换表情路径
            MemoryStream ms = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(xaml));// 必须用 UTF8 ，否则有中文时会报错 “给定编码中的字符无效”
            FlowDocument doc = System.Windows.Markup.XamlReader.Load(ms) as FlowDocument;
            doc.LineHeight = 5;

            rtbId.Document = doc;
        }
        /// <summary>
        /// 从 xaml 格式文本中加载内容
        /// </summary>
        /// <param name="rtbId"></param>
        /// <param name="xaml"></param>
        /// <param name="isLoadImg"></param>
        public static void LoadFromXaml(RichTextBox rtbId, string xaml, bool isLoadImg)
        {
            if (String.IsNullOrEmpty(xaml))
            {
                rtbId.Document.Blocks.Clear();
                return;
            }
            xaml = Regex.Replace(xaml, @"file:///([\s\S]*?)res/face/", "file:///" + Global.FaceImagePath.Replace("\\", "/"), RegexOptions.IgnoreCase);//替换表情路径
            if (isLoadImg)
            {
                string reg = @"\[\$IMG\-(\d+)\-(\d+)\-(\d+)-(.*?)-(.*?)\$\]"; //图片占位符:$1、$2、$3、$4 、$5 分别代表图片id、宽度、高度、文件夹、文件类型
                Regex re = new Regex(reg, RegexOptions.IgnoreCase | RegexOptions.Multiline);
                MatchCollection mcs = re.Matches(xaml);
                string id, width, height, src, type, recordId, tmp;
                MSL.Tool.IOHelper.Instance.CreateFolder(Global.CacheImagePath);
                foreach (Match mc in mcs)
                {
                    id = mc.Groups["1"].Value;
                    width = mc.Groups["2"].Value;
                    height = mc.Groups["3"].Value;
                    recordId = mc.Groups["4"].Value;
                    type = mc.Groups["5"].Value;
                    src = Global.CacheImagePath + recordId + "\\" + id + "." + type;

                    tmp = String.Format("file:///{0}", src.Replace(@"\", "/"));
                    reg = String.Format(@"\[\$IMG\-{0}\-(\d+)\-(\d+)-(.*?)-(.*?)\$\]", id);
                    xaml = Regex.Replace(xaml, reg, tmp, RegexOptions.IgnoreCase);
                }
            }
            MemoryStream ms = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(xaml));// 必须用 UTF8 ，否则有中文时会报错 “给定编码中的字符无效”
            FlowDocument doc = System.Windows.Markup.XamlReader.Load(ms) as FlowDocument;
            doc.LineHeight = 5;
            rtbId.Document = doc;
        }
        /// <summary>
        /// 光标位置插入文本
        /// </summary>
        /// <param name="rtbId"></param>
        /// <param name="txt"></param>
        public static void InsertTextOnCurrentPosition(RichTextBox rtbId, string txt)
        {
            rtbId.CaretPosition.InsertTextInRun(txt);
        }
        /// <summary>
        /// 光标位置插入图片
        /// </summary>
        /// <param name="rtbId"></param>
        /// <param name="txt"></param>
        public static void InsertImageOnCurrentPosition(RichTextBox rtbId, string imgPath, int width, int height)
        {
            BitmapImage bi = new BitmapImage(new Uri(imgPath));
            Image img = new Image();
            img.Source = bi;
            img.Width = width;
            img.Height = height;
            new InlineUIContainer(img, rtbId.Selection.Start);
            //InlineUIContainer container = new InlineUIContainer(image);
            //Paragraph paragraph = new Paragraph(container);

            //rtbId.Document.Blocks.Add(paragraph);
        }
        /// <summary>
        /// 保存内容到文件
        /// </summary>
        /// <param name="rtbId"></param>
        /// <returns></returns>
        public static string SaveAsFile(RichTextBox rtbId)
        {
            Microsoft.Win32.SaveFileDialog sfd = new Microsoft.Win32.SaveFileDialog();
            sfd.Filter = "Text Document(*.txt)|*.txt|网页格式|*.htm|Xaml格式|*.xaml";
            if (sfd.ShowDialog().Value)
            {
                string fileName = sfd.FileName;
                try
                {
                    string html = String.Empty;
                    if (fileName.EndsWith(".htm")) html = RichTextBoxHelper.GetHtml(rtbId);
                    if (fileName.EndsWith(".xaml")) html = RichTextBoxHelper.GetXmal(rtbId);
                    if (fileName.EndsWith(".txt")) html = RichTextBoxHelper.GetText(rtbId);

                    using (Stream s = File.OpenWrite(fileName))
                    {
                        using (StreamWriter sw = new StreamWriter(s))
                        {
                            sw.Write(html);
                            return "导出成功";
                        }
                    }
                }
                catch (IOException ex)
                {
                    return "导出失败！";
                }
            }
            return null;
        }
        /// <summary>
        /// 选中内容
        /// </summary>
        /// <returns></returns>
        public static TextRange SelectedTextRange(RichTextBox rtbId)
        {
            TextRange range = new TextRange(rtbId.Selection.Start, rtbId.Selection.End);
            return range;
        }
        /// <summary>
        /// 执行插入图像
        /// </summary>
        public static void InsertImage(RichTextBox rtbId, ImageObject image)
        {
            BitmapImage bi = new BitmapImage(new Uri(image.ImageUrl));
            Image img = new Image();
            img.Source = bi;
            img.Width = image.Width;
            img.Height = image.Height;
            img.Stretch = System.Windows.Media.Stretch.Uniform;  //图片缩放模式
            new InlineUIContainer(img, rtbId.Selection.Start);
        }
        /// <summary>
        /// 插入超链接
        /// </summary>
        public static void InsertHyperlink(RichTextBox rtbId, HyperlinkObject linkObj)
        {
            if (linkObj == null || String.IsNullOrEmpty(linkObj.Text)) return;

            Hyperlink link = new Hyperlink();
            link.IsEnabled = true;
            link.Inlines.Add(linkObj.Text);
            link.NavigateUri = new Uri(linkObj.URL);
            link.RequestNavigate += new RequestNavigateEventHandler(link_RequestNavigate);
            Paragraph paragraph = new Paragraph(link);
            rtbId.Document.Blocks.Add(paragraph);
        }
        /// <summary>
        /// 插入表格
        /// </summary>
        public static void InsertTable(RichTextBox rtbId, TableObject tableObj)
        {
            if (tableObj == null) return;
            TableRowGroup trg = new TableRowGroup();
            for (int r = 0; r < tableObj.Rows; r++)
            {
                TableRow tr = new TableRow();
                for (int c = 0; c < tableObj.Columns; c++)
                {
                    TableCell td = new TableCell();
                    td.BorderBrush = new System.Windows.Media.SolidColorBrush(System.Windows.Media.Color.FromRgb(48, 48, 48));
                    td.BorderThickness = new Thickness(0.5, 0.5, 0, 0);
                    tr.Cells.Add(td);
                }
                trg.Rows.Add(tr);
            }
            Table t = new Table();
            t.BorderBrush = new System.Windows.Media.SolidColorBrush(System.Windows.Media.Color.FromRgb(48, 48, 48));
            t.BorderThickness = new Thickness(0, 0, 0, 0.5);
            t.RowGroups.Add(trg);
            var tp = rtbId.CaretPosition.InsertParagraphBreak();
            tp.Paragraph.SiblingBlocks.InsertBefore(tp.Paragraph, t);
        }
        /// <summary>
        /// 打开浏览器
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void link_RequestNavigate(object sender, RequestNavigateEventArgs e)
        {
            System.Diagnostics.Process.Start(e.Uri.AbsolutePath.ToString());
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="rtbId"></param>
        /// <returns></returns>
        public static string GetRtf(RichTextBox rtbId)
        {
            string rtf = string.Empty;
            TextRange textRange = new TextRange(rtbId.Document.ContentStart, rtbId.Document.ContentEnd);
            using (MemoryStream ms = new MemoryStream())
            {
                textRange.Save(ms, System.Windows.DataFormats.Rtf);
                ms.Seek(0, SeekOrigin.Begin);
                StreamReader sr = new StreamReader(ms);
                rtf = sr.ReadToEnd();
            }
            return rtf;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="rtbId"></param>
        /// <param name="rtf"></param>
        public static void LoadFromRTF(RichTextBox rtbId, string rtf)
        {
            if (string.IsNullOrEmpty(rtf))
            {
                throw new ArgumentNullException();
            }
            TextRange range = new TextRange(rtbId.Document.ContentStart, rtbId.Document.ContentEnd);
            using (MemoryStream ms = new MemoryStream())
            {
                using (StreamWriter sw = new StreamWriter(ms))
                {
                    sw.Write(rtf);
                    sw.Flush();
                    ms.Seek(0, SeekOrigin.Begin);
                    range.Load(ms, System.Windows.DataFormats.Rtf);
                }
            }
        }

        /// <summary>
        /// 从 Xaml 文本中获取图片
        /// </summary>
        /// <param name="xaml"></param>
        public static ArrayList GetImages(string xaml)
        {
            string reg = "<Image\\s+source=\"(.*?)\"(.*?)/>";
            Regex re = new Regex(reg, RegexOptions.IgnoreCase | RegexOptions.Multiline);
            MatchCollection mcs = re.Matches(xaml);
            ArrayList al = new ArrayList();
            string tmp = String.Empty;
            int i = 0;
            foreach (Match mc in mcs)
            {
                tmp = mc.Value;
                if (tmp.Contains("/res/face/")) continue;
                string[] arr = new string[4];
                arr[0] = i.ToString();
                arr[1] = mc.Groups["1"].Value.Replace("file:///", "");//路径
                arr[2] = GetValueByGroupIndex(tmp, "width=\"(.*?)\"", 1);
                arr[3] = GetValueByGroupIndex(tmp, "height=\"(.*?)\"", 1);
                al.Add(arr);
                i++;
            }
            return al;
        }

        /// <summary>
        /// 单个匹配内容
        /// </summary>
        /// <param name="input">输入内容</param>
        /// <param name="pattern">表达式字符串</param>
        /// <param name="groupIndex">第几个分组, 从1开始, 0代表不分组</param>
        private static string GetValueByGroupIndex(string input, string pattern, int groupIndex)
        {
            List<string> list = new List<string>();
            Regex re = new Regex(pattern, RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.IgnorePatternWhitespace);
            MatchCollection mcs = re.Matches(input);
            string tmp = String.Empty;
            foreach (Match mc in mcs)
            {
                tmp = mc.Value;
                if (groupIndex > 0)
                    tmp = mc.Groups[groupIndex].Value;
                break;
            }
            return tmp;
        }
    }
}
